package main

import (
	"errors"
	"flag"
	"fmt"
	"net"
	"os"
	"strings"
)

var exit_all = make(chan string)

func recv_msg(conn net.Conn, quit chan<- int) {
	defer func() {
		quit <- 0
	}()
	for {
		recv_buf := make([]byte, 1024)
		lenght, err := conn.Read(recv_buf) //接受客户端数据
		if err != nil {
			break
		}
		data := string(recv_buf[:lenght])

		if strings.EqualFold(data, "Quit") {
			break
		} else {
			fmt.Printf("\rclient:%s", data) //打印客户端发送的内容
			fmt.Printf("\rserver:")
		}

	}
}
func send_msg(conn net.Conn, quit chan<- int, exit chan<- int) {
	var data string //输入发送的内容
	defer func() {
		quit <- 0
		//	time.Sleep(1 * time.Second)
		exit <- 0
	}()
	for {
		data = ""
		fmt.Printf("server:")
		fmt.Scanln(&data)
		send_buf := []byte(data)
		if strings.EqualFold(data, "Exit") {
			break
		}
		_, err := conn.Write(send_buf) //向服务器发送数据
		if err != nil {
			fmt.Println(err)
			continue //发送出现错误，继续
		}
	}
}
func close_msg(conn net.Conn, quit <-chan int, exit <-chan int) {
	for {
		select { //此处仅仅为了用select而用
		case <-quit:
			conn.Close()
			fmt.Printf("\rclient is disconnected\n")
			fmt.Println("wait for connection...")
		case <-exit:
			exit_all <- "EXIT ALL"
		}
	}
}

func accept_conn(listener net.Listener) {
	for {
		conn, err := listener.Accept() //接受客户端请求
		if err != nil {
			fmt.Println(err)
			continue
		}
		fmt.Println("connect successfunlly!")

		quit, exit := make(chan int), make(chan int)
		go recv_msg(conn, quit)
		go send_msg(conn, quit, exit)
		go close_msg(conn, quit, exit)
	}
}

func CreateListener() (net.Listener, error) {
	fd := flag.Bool("fdfromfile", false, "pass param indicate whether is create socket from file or not")
	flag.Parse()

	if !*fd {
		addr, err := net.ResolveTCPAddr("tcp", ":9005")
		if err != nil {
			return nil, fmt.Errorf("fail to resolve addr:%v", err)
		}
		listener, err := net.ListenTCP("tcp", addr)
		if err != nil {
			return nil, fmt.Errorf("fail to listen TCP: %v", err)
		}
		return listener, nil
	} else {
		file := os.NewFile(3, "/tmp/sock-go-graceful-restart")
		listener, err := net.FileListener(file)
		if err != nil {
			return nil, errors.New("File to recover socket from file descriptor: " + err.Error())
		}
		listenerTCP, ok := listener.(*net.TCPListener)
		if !ok {
			return nil, fmt.Errorf("File descriptor %d is not a valid TCP socket", fd)
		}

		return listenerTCP, nil
	}
	return nil, nil
}
func main() {
	//监听端口
	listener, err := CreateListener()
	if err != nil {
		fmt.Println(err)
		return
	}
	go accept_conn(listener)
	for v := range exit_all {
		fmt.Println(v)
		break
	}
}
